#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "cCubeTree.h"
#include "component.h"

#define MAX_WORMS 10

cCubeTree::cCubeTree(Sync* sync) :
		Component(sync) {
}

cCubeTree::~cCubeTree() {
	delete[] worm;

	glDeleteBuffers(1, &cubeVertices);
	glDeleteBuffers(1, &cubePolygon);
	glDeleteBuffers(1, &cubeEdges);
}

void cCubeTree::initialize() {
	worm_count = 0;
	worm = new Worm[MAX_WORMS];
	for (int i = 0; i < MAX_WORMS; i++) {
		this->initWorm(i, 0);
	}

	const float S = 1.0f;
	GLfloat vertices[] = {
			-S, S,-S,  S, S,-S,
			-S,-S,-S,  S,-S,-S,
			-S, S, S,  S, S, S,
			-S,-S, S,  S,-S, S,
	};

	GLuint faces[] = {
			0,1,2, 1,3,2, // Front
			4,7,5, 4,6,7, // Back
			0,4,1, 1,4,5, // Top
			2,3,7, 2,7,6, // Bottom
			1,7,3, 1,5,7, // Right
			0,2,4, 4,2,6, // Left
	};

	GLuint edges[] = {
			0,1, 1,3, 3,2, 2,0, // Front
			4,6, 6,7, 7,5, 5,4, // Back
			0,4, 1,5, 3,7, 2,6 // Middle
	};


	glGenBuffers(1, &cubeVertices);
	glGenBuffers(1, &cubePolygon);
	glGenBuffers(1, &cubeEdges);

	glBindBuffer(GL_ARRAY_BUFFER, cubeVertices);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8*3, NULL, GL_DYNAMIC_DRAW);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*8*3, vertices);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubePolygon);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, NULL, GL_STATIC_DRAW);
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*6*2*3, faces);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeEdges);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*12, NULL, GL_STATIC_DRAW);
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*2*12, edges);
}

void cCubeTree::draw(float time, float dt, float alpha) {
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	gluPerspective(90, 1, 1, 1000);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glClear(GL_DEPTH_BUFFER_BIT);

	//glTranslatef(0, 0, -3);
	//glRotated(time*3.14*10, 1, 1, 0);


	glEnable(GL_FOG);
	glFogi(GL_FOG_MODE, GL_EXP2);
	GLfloat fogColor[4] = {1, 1, 1, 1};
	glFogfv (GL_FOG_COLOR, fogColor);
	glFogf (GL_FOG_DENSITY, .01f);
	glHint (GL_FOG_HINT, GL_FASTEST);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_INDEX_ARRAY);

	glBindBuffer(GL_ARRAY_BUFFER, cubeVertices);

	const float scale = 1.00
			+ sync->channel(SYNC_SINE)*0.2
			+ sync->channel(SYNC_RANDOM)*0.25;

	const float fraction = time - (int)time;
	const int cubes = 100;
	for (int i = 0; i < cubes; i++) {
		float alpha = i/float(cubes);
		float t = alpha*3.1415 + time*0.1;
		glLoadIdentity();
		float x = sin(10*t)*20;
		float y = sin(8*t)*20;
		float z = sin(2*t)*20;
		glTranslatef(x,y,z-50);

		// draw faces
		glColor4f(0,0,0,1);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubePolygon);
		glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*3, NULL);
		glIndexPointer(GL_UNSIGNED_BYTE, sizeof(GLuint)*1, &cubePolygon);
		glDrawElements(GL_TRIANGLES, 6*2*3, GL_UNSIGNED_INT, NULL);

		// draw wires
		glColor4f(1,0,0,1);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeEdges);
		glIndexPointer(GL_UNSIGNED_BYTE, sizeof(GLuint)*1, &cubeEdges);
		glScalef(scale, scale, scale);
		glDrawElements(GL_LINES, 12*2, GL_UNSIGNED_INT, NULL);
	}

	glDisableClientState(GL_INDEX_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisable(GL_FOG);

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
}

void cCubeTree::initWorm(int i, float time) {
	float x = frand(-2, 2);
	float y = frand(-2, 2);
	float z = frand(-2, 0);
	worm[i].position = Vector(x, y, z);
	worm[i].speed = frand(0.5f, 1.5f);
	worm[i].timeStart = time + frand(0, 2);
}
